home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Sound Cards
/
Programming Sound Cards.iso
/
sound_06
/
bank.c
< prev
next >
Wrap
Text File
|
1995-01-01
|
7KB
|
298 lines
/*
BANK.C
28-jun-88, Marc Savary, Ad Lib Inc.
Timbre Bank Manager.
Refer to PLAY.C for compilation instructions.
*/
#include <stdio.h>
#include <fcntl.h>
#include "bank.h"
#define TIMBRE_NAME_SIZE 9
#define TIMBRE_DEF_LEN 28
#define TIMBRE_DEF_SIZE (TIMBRE_DEF_LEN * sizeof( int))
#define MAJOR_VERSION 1
#define MINOR_VERSION 0
#ifdef LATTICE
extern char * getmem();
extern long lseek();
#endif
#ifdef MICROSOFT
#include <malloc.h>
#include <string.h>
#include <io.h>
#include <stdio.h>
#include <sys\types.h>
#include <sys\stat.h>
#define open(x,y) open(x,y,S_IWRITE)
#define rlsmem(x,y) free(x)
#define getmem(x) malloc(x)
#define setmem(x,y,z) memset(x,z,y)
#define movmem(x,y,z) memmove(y,x,z)
#endif
/*
Open the timbre bank 'bankName'. If does not exist, and
'creatFlag' is != 0, create it.
Return a pointer to the descriptor, or NULL if error.
*/
BankPtr OpenBank( bankName, createFlag)
char * bankName;
{
int file;
BankRec * bP;
bP = (BankRec *) getmem( sizeof( BankRec));
if( NULL == bP)
return NULL;
file = open( bankName, O_RDWR + O_RAW);
if( file == -1) {
if( ! createFlag || -1 == ( file = CreateBank( bankName))) {
rlsmem( bP, sizeof( BankRec));
return NULL;
}
}
bP->fileId = file;
bP->inMemFlag = 0;
bP->modified = 0;
return bP;
} /* OpenBank() */
/*
Close the already opened bank. If the bank has beed modified,
write the modifications to file.
*/
int CloseBank( bankPtr)
BankPtr bankPtr;
{
int len;
if( bankPtr->modified) {
lseek( bankPtr->fileId, 0L, 0);
len = sizeof( TimFileBank) + bankPtr->timbBank->nrTimbre
* ( TIMBRE_DEF_SIZE + TIMBRE_NAME_SIZE);
write( bankPtr->fileId, (char *) bankPtr->timbBank, len);
}
close( bankPtr->fileId);
if( bankPtr->inMemFlag) {
rlsmem( bankPtr->timbBank, len);
}
rlsmem( bankPtr, sizeof( BankRec));
return 1;
} /* CloseBank() */
/*
Load all the bank in memory, for fast access. Allocate required
memory.
return 0 if error.
*/
int LoadBank( bankPtr)
BankPtr bankPtr;
{
TimFileBank tB, * tBPtr;
int res, len, i;
long pos;
pos = lseek( bankPtr->fileId, 0L, 0);
res = read( bankPtr->fileId, (char *) &tB, sizeof( TimFileBank));
len = tB.nrTimbre * (TIMBRE_NAME_SIZE + TIMBRE_DEF_SIZE);
len += sizeof( TimFileBank);
tBPtr = ( TimFileBank *) getmem( len);
if( tBPtr == NULL)
return 0;
pos = lseek( bankPtr->fileId, 0L, 0);
read( bankPtr->fileId, (char *) tBPtr, len);
bankPtr->timbBank = tBPtr;
bankPtr->inMemFlag = 1;
return 1;
} /* LoadBank() */
/*
Return the timbre definition in 'timbreDefPtr'.
If 'timbreName' is not an empty string, search for in the index of
'bankPtr' and set 'timbreIndex' to the found position value.
If 'timbreName' is an empty string, use 'timbreIndex' as position.
*/
int GetTimbre( timbreName, timbreIndex, timbreDefPtr, bankPtr)
char * timbreName; /* name of timbre def. to return */
int * timbreIndex; /* used if 'timbreName' == "" */
int * timbreDefPtr; /* array for save to timbre def. */
BankPtr bankPtr; /* timbre bank ref. */
{
if( bankPtr->inMemFlag)
return InMemGetTimbre( timbreName, timbreIndex, timbreDefPtr, bankPtr);
else
return InFileGetTimbre( timbreName, timbreIndex, timbreDefPtr, bankPtr);
} /* GetTimbre() */
/*
If 'timbreName' exists in the bank, replace its definition by 'timbreDef'.
If not, add definition to the end of the bank.
Return in 'timbIndex' the relative position of timbre.
*/
int AddTimbre( timbreName, timbIndex, timbreDef, bankPtr)
char * timbreName;
int * timbIndex;
int * timbreDef;
BankPtr bankPtr;
{
int tmpDef[ TIMBRE_DEF_LEN];
int index, mv, oldLen, len, nlen, i;
char * defPtr, * dest;
TimFileBank * tb1, * tb2;
if( ! bankPtr->inMemFlag && ! LoadBank( bankPtr))
return 0;
if( GetTimbre( timbreName, &index, tmpDef, bankPtr)) {
/* replace it ... */
defPtr = (char *)bankPtr->timbBank + bankPtr->timbBank->offsetDef
+ index * TIMBRE_DEF_SIZE;
movmem( timbreDef, defPtr, TIMBRE_DEF_SIZE);
*timbIndex= index;
}
else {
/* add to the end. */
tb1 = bankPtr->timbBank;
*timbIndex = tb1->nrTimbre;
oldLen = tb1->nrTimbre * ( TIMBRE_NAME_SIZE + TIMBRE_DEF_SIZE)
+ sizeof( TimFileBank);
len = oldLen + TIMBRE_NAME_SIZE + TIMBRE_DEF_SIZE;
tb2 = ( TimFileBank *) getmem( len);
if( tb2 == NULL)
return 0;
mv = tb1->nrTimbre * TIMBRE_NAME_SIZE + sizeof( TimFileBank);
dest = (char *) tb2;
movmem( tb1, dest, mv);
dest += mv;
nlen= strlen( timbreName);
movmem( timbreName, dest, TIMBRE_NAME_SIZE);
setmem( dest + nlen, TIMBRE_NAME_SIZE - nlen, 0);
dest += TIMBRE_NAME_SIZE;
mv = tb1->nrTimbre * TIMBRE_DEF_SIZE;
movmem( (char *)tb1 + tb1->offsetDef, dest, mv);
dest += mv;
movmem( timbreDef, dest, TIMBRE_DEF_SIZE);
rlsmem( tb1, oldLen);
tb2->offsetDef += TIMBRE_NAME_SIZE;
tb2->nrTimbre++;
bankPtr->timbBank = tb2;
}
bankPtr->modified = 1;
return 1;
} /* AddTimbre() */
/*
Create a new timbre bank and initialize the header.
Return the file id.
*/
static int CreateBank( bankName)
char * bankName;
{
int file;
TimFileBank tB;
file = open( bankName, O_RDWR + O_RAW + O_CREAT);
if( -1 == file)
return 0;
tB.majorVersion = MAJOR_VERSION;
tB.minorVersion = MINOR_VERSION;
tB.nrTimbre = 0;
tB.offsetDef = sizeof( TimFileBank);
write( file, (char *) &tB, sizeof( TimFileBank));
/* Lattice C Bug: lseek does not work on newly created files !! ??? */
close( file);
file = open( bankName, O_RDWR + O_RAW);
return file;
} /* CreateBank() */
/*
Do the work of 'GetTimbre()' when bank is not in memory.
*/
static int InFileGetTimbre( timbreName, timbreIndex, timbreDefPtr, bankPtr)
char * timbreName;
int * timbreIndex;
int * timbreDefPtr;
BankPtr bankPtr;
{
TimFileBank tB;
char indexName[ TIMBRE_NAME_SIZE];
int i;
lseek( bankPtr->fileId, 0L, 0);
read( bankPtr->fileId, (char *) &tB, sizeof( TimFileBank));
i = *timbreIndex;
if( *timbreName) {
for( i = 0; i < tB.nrTimbre; i++) {
read( bankPtr->fileId, indexName, TIMBRE_NAME_SIZE);
if( 0 == strcmp( timbreName, indexName))
break;
}
}
if( i >= tB.nrTimbre)
return 0;
lseek( bankPtr->fileId,
(long)( tB.offsetDef + i * TIMBRE_DEF_SIZE), 0);
read( bankPtr->fileId, (char *) timbreDefPtr, TIMBRE_DEF_SIZE);
*timbreIndex = i;
return 1;
} /* InFileGetTimbre() */
/*
Do the work of 'GetTimbre()' when bank is in memory.
*/
static int InMemGetTimbre( timbreName, timbreIndex, timbreDefPtr, bankPtr)
char * timbreName;
int * timbreIndex; /* in/out */
int * timbreDefPtr;
BankPtr bankPtr;
{
TimFileBank tB;
char * defPtr, * iP;
int i, nrTimbre;
i = * timbreIndex;
nrTimbre = bankPtr->timbBank->nrTimbre;
iP = (char *)bankPtr->timbBank + sizeof( TimFileBank);
if( *timbreName) {
for( i = 0; i < nrTimbre; i++, iP += TIMBRE_NAME_SIZE)
if( 0 == strcmp( timbreName, iP))
break;
}
if( i >= nrTimbre)
return 0;
defPtr = (char *)bankPtr->timbBank + bankPtr->timbBank->offsetDef;
movmem( defPtr + i * TIMBRE_DEF_SIZE, timbreDefPtr, TIMBRE_DEF_SIZE);
*timbreIndex = i;
return 1;
} /* InMemGetTimbre() */